home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1992, 1993, David Koblas (koblas@netcom.com) | */
- /* | | */
- /* | Permission to use, copy, modify, and to distribute this software | */
- /* | and its documentation for any purpose is hereby granted without | */
- /* | fee, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. There is no | */
- /* | representations about the suitability of this software for | */
- /* | any purpose. this software is provided "as is" without express | */
- /* | or implied warranty. | */
- /* | | */
- /* +-------------------------------------------------------------------+ */
-
- /*
- ** PaintRegion.c -- Hopefully all of the routines to get,set and
- ** manipulate the selection region.
- **
- ** Not part of the "selection" operation, since this really
- ** need to know lots of hidden information (why?)
- */
-
- #include <math.h>
- #include <X11/IntrinsicP.h>
- #include <X11/StringDefs.h>
- #include <X11/cursorfont.h>
- #include <X11/Xatom.h>
- #include <X11/Xaw/Grip.h>
- #include "PaintP.h"
-
- #define SHAPE
-
- #ifdef SHAPE
- #include <X11/extensions/shape.h>
- #endif
-
- static void regionExpose(Widget, PaintWidget, XEvent *, Boolean *);
-
- #define regionRedraw(pw) regionExpose(pw->paint.region.child, pw, NULL, NULL)
-
- #define BoolStr(flg) ((flg) ? "True" : "False")
-
- #undef INTERACTIVE
-
- /*
- ** Border Width of child widget
- */
- #define BW 0
-
- /*
- ** 2x2 matrix stuff
- **
- */
-
- #define XFORM(x,y,mat,nx,ny) nx = mat[0][0] * x + mat[0][1] * y; \
- ny = mat[1][0] * x + mat[1][1] * y
- #define COPY_MAT(s,d) d[0][0] = s[0][0]; d[0][1] = s[0][1]; d[1][0] = s[1][0]; d[1][1] = s[1][1]
-
- #define INVERT_MAT(mat, inv) do { \
- float _d = 1.0 / (mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]); \
- (inv)[0][0] = (mat)[1][1] * _d; \
- (inv)[1][1] = (mat)[0][0] * _d; \
- (inv)[0][1] = -(mat)[0][1] * _d; \
- (inv)[1][0] = -(mat)[1][0] * _d; \
- } while (0)
- #define ZERO(v) (((v) > -1e-5) && ((v) < 1e-5))
-
- #ifndef MIN
- #define MIN(a,b) (((a) < (b)) ? (a) : (b))
- #endif
- #ifndef MAX
- #define MAX(a,b) (((a) > (b)) ? (a) : (b))
- #endif
- #ifndef SIGN
- #define SIGN(a) (((a) < 0) ? -1 : 1)
- #endif
- #ifndef ABS
- #define ABS(a) ((a > 0) ? (a) : 0 - (a))
- #endif
-
- #define PRINT_MAT(msg,mat) printf("matrix %s =\n\t%f %f\n\t%f %f\n", msg, \
- mat[0][0], mat[0][1], mat[1][0], mat[1][1])
- #define MKMAT(pw) do { \
- pwMatrix m; \
- m[0][0] = pw->paint.region.scaleX; \
- m[1][1] = pw->paint.region.scaleY; \
- m[0][1] = m[1][0] = 0.0; \
- mm(pw->paint.region.rotMat, m, pw->paint.region.mat); \
- } while (0)
-
- static pwMatrix matIdentity = { { 1, 0 }, { 0, 1 } };
-
- static void doCallbacks(PaintWidget pw, Boolean flag)
- {
- PaintWidget tpw = (pw->paint.paint == None) ? pw : (PaintWidget)pw->paint.paint;
- int i;
-
- XtCallCallbackList((Widget)tpw, tpw->paint.regionCalls, (XtPointer)flag);
- for (i = 0; i < tpw->paint.paintChildrenSize; i++) {
- PaintWidget p = (PaintWidget)tpw->paint.paintChildren[i];
- XtCallCallbackList((Widget)p, p->paint.regionCalls, (XtPointer)flag);
- }
- }
-
- static void mm(pwMatrix a, pwMatrix b, pwMatrix r)
- {
- float t00, t10, t01, t11;
-
- t00 = a[0][0] * b[0][0] + a[0][1] * b[1][0];
- t01 = a[0][0] * b[0][1] + a[0][1] * b[1][1];
- t10 = a[1][0] * b[0][0] + a[1][1] * b[1][0];
- t11 = a[1][0] * b[0][1] + a[1][1] * b[1][1];
-
- r[0][0] = t00;
- r[1][0] = t10;
- r[0][1] = t01;
- r[1][1] = t11;
- }
-
- /*
- ** PwRegionSet -- set the active image region
- ** add handles and other useful things
- ** if the pix == None, use the current paint info in rect
- ** else use the pixmap.
- **
- */
- static void buildSources(PaintWidget pw)
- {
- if (pw->paint.region.sourceImg == NULL) {
- pw->paint.region.sourceImg = XGetImage(XtDisplay(pw),
- pw->paint.region.source, 0, 0,
- pw->paint.region.orig.width,
- pw->paint.region.orig.height, AllPlanes, ZPixmap);
- }
-
- if (pw->paint.region.mask == None)
- return;
-
- if (pw->paint.region.maskImg == NULL) {
- pw->paint.region.maskImg = XGetImage(XtDisplay(pw),
- pw->paint.region.mask, 0, 0,
- pw->paint.region.orig.width,
- pw->paint.region.orig.height, AllPlanes, ZPixmap);
- }
- }
-
- static void resizeImg(PaintWidget pw, pwMatrix inv,
- Pixmap *pix, XImage *pixSrc, Pixmap *msk, XImage *mskSrc, Pixmap *shape)
- {
- int width, height, depth;
- int x, y;
- XImage *pixDst, *mskDst, *shapeDst = NULL;
- int sourceW, sourceH;
- int ix, iy, fx, fy, cx, cy;
- float dx, dy, sx, sy;
-
- if (pixSrc == NULL || pix == NULL)
- return;
- if (pw->paint.region.rect.width == 0 || pw->paint.region.rect.height == 0)
- return;
-
- /*
- ** Construct the dest pixmap.
- */
-
- if (*pix != None)
- XFreePixmap(XtDisplay(pw), *pix);
- if (*msk != None && mskSrc != NULL)
- XFreePixmap(XtDisplay(pw), *msk);
-
- depth = pixSrc->depth;
-
- width = pw->paint.region.rect.width / GET_ZOOM(pw);
- height = pw->paint.region.rect.height / GET_ZOOM(pw);
-
- *pix = XCreatePixmap(XtDisplay(pw), XtWindow(pw), width, height, depth);
- pixDst = XCreateImage(XtDisplay(pw), pw->paint.visual,
- depth, ZPixmap, 0, NULL, width, height, 32, 0);
- pixDst->data = (char*)XtMalloc(height * pixDst->bytes_per_line);
-
- if (mskSrc != NULL) {
- *msk = XCreatePixmap(XtDisplay(pw), XtWindow(pw), width, height, 1);
- mskDst = XCreateImage(XtDisplay(pw), pw->paint.visual,
- 1, ZPixmap, 0, NULL, width, height, 32, 0);
- mskDst->data = (char*)XtMalloc(height * mskDst->bytes_per_line);
- #ifdef SHAPE
- if (shape != NULL) {
- *shape = XCreatePixmap(XtDisplay(pw), XtWindow(pw), width, height, 1);
- shapeDst = XCreateImage(XtDisplay(pw), pw->paint.visual,
- 1, ZPixmap, 0, NULL, width, height, 32, 0);
- shapeDst->data = (char*)XtMalloc(height * shapeDst->bytes_per_line);
- }
- #endif
- }
-
-
- cx = pw->paint.region.orig.width / 2;
- cy = pw->paint.region.orig.height / 2;
- fx = (int)(-width / 2);
- fy = (int)(-height / 2);
- sourceW = pixSrc->width;
- sourceH = pixSrc->height;
- for (y = 0, dy = fy; y < height; y++, dy++) {
- for (x = 0, dx = fx; x < width; x++, dx++) {
- XFORM(dx,dy,inv,sx,sy);
- ix = (sx + cx);
- iy = (sy + cy);
- if (ix >= 0 && ix < sourceW && iy >= 0 && iy < sourceH) {
- xxPutPixel(pixDst, x, y, xxGetPixel(pixSrc, ix, iy));
- if (mskSrc != NULL)
- XPutPixel(mskDst, x, y, XGetPixel(mskSrc, ix, iy));
- #ifdef SHAPE
- if (shapeDst != NULL)
- XPutPixel(shapeDst, x, y, True);
- #endif
- } else if (mskSrc != NULL) {
- XPutPixel(mskDst, x, y, False);
- #ifdef SHAPE
- if (shapeDst != NULL)
- XPutPixel(shapeDst, x, y, False);
- #endif
- }
- }
- }
-
- XPutImage(XtDisplay(pw), *pix, pw->paint.tgc, pixDst, 0, 0, 0, 0, width, height);
- XDestroyImage(pixDst);
-
- if (mskSrc != NULL) {
- XPutImage(XtDisplay(pw), *msk, pw->paint.mgc, mskDst, 0, 0, 0, 0, width, height);
- XDestroyImage(mskDst);
- }
- #ifdef SHAPE
- if (shapeDst != NULL) {
- XPutImage(XtDisplay(pw), *shape, pw->paint.mgc, shapeDst, 0, 0, 0, 0, width, height);
- XDestroyImage(shapeDst);
- }
- #endif
- }
-
- static void regionCreateNotMask(PaintWidget pw)
- {
- if (pw->paint.region.rect.width == 0 || pw->paint.region.rect.height == 0)
- return;
-
- if (pw->paint.region.mask == None)
- return;
-
- if (pw->paint.region.notMask != None)
- XFreePixmap(XtDisplay(pw), pw->paint.region.notMask);
-
- pw->paint.region.notMask = XCreatePixmap(XtDisplay(pw), XtWindow(pw),
- pw->paint.region.rect.width, pw->paint.region.rect.height, 1);
- XSetFunction(XtDisplay(pw), pw->paint.mgc, GXcopyInverted);
- XCopyArea(XtDisplay(pw), pw->paint.region.mask, pw->paint.region.notMask, pw->paint.mgc,
- 0, 0, pw->paint.region.rect.width, pw->paint.region.rect.height, 0, 0);
- XSetFunction(XtDisplay(pw), pw->paint.mgc, GXcopy);
-
- XSetClipMask(XtDisplay(pw), pw->paint.region.bg_gc, pw->paint.region.notMask);
- XSetClipMask(XtDisplay(pw), pw->paint.region.fg_gc, pw->paint.region.mask);
- }
-
- static void createVtxPts(PaintWidget pw, float vtx[9][2], Boolean flag, Boolean useZoom)
- {
- int zoom;
- int i;
- int x0, x1, y0, y1;
- int width = pw->paint.region.orig.width;
- int height = pw->paint.region.orig.height;
-
- if (useZoom)
- zoom = GET_ZOOM(pw);
- else
- zoom = 1;
-
- x0 = (-width / 2);
- x1 = ( width + x0);
- y0 = (-height / 2);
- y1 = ( height + y0);
- x0 *= zoom;
- x1 *= zoom;
- y0 *= zoom;
- y1 *= zoom;
-
- /*
- ** Watch out, these are points 0,1, and _3__
- */
- XFORM(x0,y0,pw->paint.region.mat,vtx[0][0],vtx[0][1]);
- XFORM(x1,y0,pw->paint.region.mat,vtx[1][0],vtx[1][1]);
- XFORM(x0,y1,pw->paint.region.mat,vtx[3][0],vtx[3][1]);
-
- if (flag) {
- XFORM(x1,y1,pw->paint.region.mat,vtx[2][0],vtx[2][1]);
-
- for (i = 0; i < 4; i++) {
- vtx[i][0] += pw->paint.region.centerX * zoom;
- vtx[i][1] += pw->paint.region.centerY * zoom;
- }
- } else {
- /*
- ** sort the points, so that point 0,0 is top left corner
- */
- if (vtx[0][0] > vtx[1][0]) {
- float t = x0;
- x0 = x1;
- x1 = t;
- }
- if (vtx[0][1] > vtx[3][1]) {
- float t = y0;
- y0 = y1;
- y1 = t;
- }
-
- XFORM(x0,y0,pw->paint.region.mat,vtx[0][0],vtx[0][1]);
- XFORM( 0,y0,pw->paint.region.mat,vtx[1][0],vtx[1][1]);
- XFORM(x1,y0,pw->paint.region.mat,vtx[2][0],vtx[2][1]);
-
- XFORM(x0, 0,pw->paint.region.mat,vtx[3][0],vtx[3][1]);
- XFORM( 0, 0,pw->paint.region.mat,vtx[4][0],vtx[4][1]);
- XFORM(x1, 0,pw->paint.region.mat,vtx[5][0],vtx[5][1]);
-
- XFORM(x0,y1,pw->paint.region.mat,vtx[6][0],vtx[6][1]);
- XFORM( 0,y1,pw->paint.region.mat,vtx[7][0],vtx[7][1]);
- XFORM(x1,y1,pw->paint.region.mat,vtx[8][0],vtx[8][1]);
- }
- }
-
- static void doResize(PaintWidget pw)
- {
- pwMatrix inv;
- Pixmap shape, *shp = &shape;
-
- buildSources(pw);
-
- /*
- ** First find out the bounding extent of the transformed
- ** area, then scale it to fit inside of the "region box"
- */
-
- if (pw->paint.region.maskImg == NULL) {
- Boolean needMask = False;
- float vtx[9][2];
- float minX, minY, maxX, maxY;
- int x, cmin, cmax;
-
- createVtxPts(pw, vtx, True, False);
-
- minX = MIN(vtx[0][0],MIN(vtx[1][0],MIN(vtx[2][0],vtx[3][0])));
- minY = MIN(vtx[0][1],MIN(vtx[1][1],MIN(vtx[2][1],vtx[3][1])));
- maxX = MAX(vtx[0][0],MAX(vtx[1][0],MAX(vtx[2][0],vtx[3][0])));
- maxY = MAX(vtx[0][1],MAX(vtx[1][1],MAX(vtx[2][1],vtx[3][1])));
-
- /*
- ** After computing min, max see if there are points
- ** on all vertices, if so then set the correct return code
- */
- for (cmin = cmax = x = 0; x < 4; x++) {
- if ((int)vtx[x][0] == (int)minX)
- cmin++;
- else if ((int)vtx[x][0] == (int)maxX)
- cmax++;
- }
- needMask |= (cmin != 2 || cmax != 2);
- for (cmin = cmax = x = 0; x < 4; x++) {
- if ((int)vtx[x][1] == (int)minY)
- cmin++;
- else if ((int)vtx[x][1] == (int)maxY)
- cmax++;
- }
- needMask |= (cmin != 2 || cmax != 2);
-
- if (needMask) {
- Pixmap mask;
- GC mgc;
-
- /*
- ** If the image we just transformed needs a mask
- ** and one doesn't exist, construct one.
- */
- mask = pw->paint.region.mask = XCreatePixmap(XtDisplay(pw), XtWindow(pw),
- pw->paint.region.orig.width, pw->paint.region.orig.height, 1);
- mgc = GET_MGC(pw, mask);
- XSetFunction(XtDisplay(pw), mgc, GXset);
- XFillRectangle(XtDisplay(pw), mask, mgc, 0, 0,
- pw->paint.region.orig.width,
- pw->paint.region.orig.height);
- XSetFunction(XtDisplay(pw), mgc, GXcopy);
-
- buildSources(pw);
-
- if (pw->paint.region.fg_gc == None) {
- pw->paint.region.fg_gc = XCreateGC(XtDisplay(pw), XtWindow(pw), 0, 0);
- pw->paint.region.bg_gc = XCreateGC(XtDisplay(pw), XtWindow(pw), 0, 0);
- }
- }
- }
-
- INVERT_MAT(pw->paint.region.mat, inv);
- #ifdef SHAPE
- if (pw->paint.region.maskImg == NULL || GET_ZOOM(pw) != 1)
- shp = NULL;
- #else
- shp = NULL;
- #endif
- resizeImg(pw, inv, &pw->paint.region.source, pw->paint.region.sourceImg,
- &pw->paint.region.mask, pw->paint.region.maskImg, shp);
- regionCreateNotMask(pw);
-
- #ifdef SHAPE
- if (shp != NULL) {
- XShapeCombineMask(XtDisplay(pw), XtWindow(pw->paint.region.child),
- ShapeBounding, 0, 0, shape, ShapeSet);
- XFreePixmap(XtDisplay(pw), shape);
- }
- #endif
-
- pw->paint.region.needResize = False;
- }
-
- static void drawRegionBox(PaintWidget pw, Boolean flag)
- {
- static XPoint xvtxLast[5];
- XPoint xvtx[5];
- float vtx[9][2];
- Window window = XtWindow(pw);
- int i;
-
- createVtxPts(pw, vtx, True, True);
-
- xvtx[0].x = vtx[0][0]; xvtx[0].y = vtx[0][1];
- xvtx[1].x = vtx[1][0]; xvtx[1].y = vtx[1][1];
- xvtx[2].x = vtx[2][0]; xvtx[2].y = vtx[2][1];
- xvtx[3].x = vtx[3][0]; xvtx[3].y = vtx[3][1];
- xvtx[4].x = vtx[0][0]; xvtx[4].y = vtx[0][1];
-
- for (i = 0; i < 5; i++) {
- xvtx[i].x += pw->paint.region.child->core.x;
- xvtx[i].y += pw->paint.region.child->core.y;
- }
-
- if (pw->paint.region.isDrawn) {
- XDrawLines(XtDisplay(pw), window, pw->paint.xgc, xvtxLast, 5, CoordModeOrigin);
- pw->paint.region.isDrawn = False;
- }
-
- if (flag) {
- XDrawLines(XtDisplay(pw), window,
- pw->paint.xgc, xvtx, 5, CoordModeOrigin);
- memcpy(xvtxLast, xvtx, sizeof(xvtxLast));
- pw->paint.region.isDrawn = True;
- }
- }
-
- /*
- **
- */
-
- static void regionResizeWindow(PaintWidget pw, Boolean sameCenter)
- {
- int zoom = GET_ZOOM(pw);
- int minX, minY, maxX, maxY;
- int width, height, dx, dy, nx, ny;
- int newX, newY;
- int i;
- float vtx[9][2];
-
- #ifndef INTERACTIVE
- if (pw->paint.region.isTracking)
- return;
- #endif
-
- createVtxPts(pw, vtx, False, False);
-
- minX = MIN(vtx[0][0], vtx[6][0]);
- maxX = MAX(vtx[2][0], vtx[8][0]);
- minY = MIN(vtx[0][1], vtx[2][1]);
- maxY = MAX(vtx[6][1], vtx[8][1]);
-
- width = maxX - minX + 0.5;
- height = maxY - minY + 0.5;
-
- newX = pw->paint.region.centerX - (width / 2);
- newY = pw->paint.region.centerY - (height / 2);
-
- newX += pw->paint.region.rect.x;
- newY += pw->paint.region.rect.y;
- if (!sameCenter) {
- pw->paint.region.centerX = width / 2;
- pw->paint.region.centerY = height / 2;
- } else {
- pw->paint.region.centerX = width / 2;
- pw->paint.region.centerY = height / 2;
- }
-
- if ((width *= zoom) < 10)
- width = 10;
- if ((height *= zoom) < 10)
- height = 10;
- XtResizeWidget(pw->paint.region.child, width, height, BW);
- nx = (newX - pw->paint.zoomX) * zoom;
- ny = (newY - pw->paint.zoomY) * zoom;
- XtMoveWidget(pw->paint.region.child, nx - BW, ny - BW);
-
- pw->paint.region.rect.x = newX;
- pw->paint.region.rect.y = newY;
- pw->paint.region.rect.width = width;
- pw->paint.region.rect.height = height;
-
- /*
- ** Now place all the grips.
- */
- createVtxPts(pw, vtx, False, True);
- width = pw->paint.region.grip[0]->core.width;
- height = pw->paint.region.grip[0]->core.height;
- dx = pw->paint.region.centerX * zoom - width / 2;
- dy = pw->paint.region.centerY * zoom - height / 2;
- for (i = 0; i < 9; i++) {
- int x, y;
-
- if (i == 4)
- continue;
-
- x = vtx[i][0] + dx;
- y = vtx[i][1] + dy;
-
- if (x < 0)
- x = 0;
- if (y < 0)
- y = 0;
- if (x + width > pw->paint.region.rect.width)
- x = pw->paint.region.rect.width - width;
- if (y + height > pw->paint.region.rect.height)
- y = pw->paint.region.rect.height - height;
-
- XtMoveWidget(pw->paint.region.grip[i], x, y);
- }
- }
-
- /*
- **
- */
-
- static void moveGrips(PaintWidget pw)
- {
- int width, height;
- int i, gx, gy;
- Dimension w, h;
- Widget widget = pw->paint.region.grip[0];
-
- w = widget->core.width;
- h = widget->core.height;
- width = widget->core.parent->core.width;
- height = widget->core.parent->core.height;
-
- for (i = 0; i < 9; i++) {
- if (i == 4)
- continue;
-
- switch (i % 3) {
- case 0: gx = 0; break;
- case 1: gx = width / 2 - w / 2; break;
- case 2: gx = width - w; break;
- }
- switch (i / 3) {
- case 0: gy = 0; break;
- case 1: gy = height / 2 - h / 2; break;
- case 2: gy = height - h; break;
- }
-
- XtMoveWidget(pw->paint.region.grip[i], gx, gy);
- }
- }
-
- static void gripPress(Widget w, PaintWidget pw, XButtonEvent *event, Boolean *junk)
- {
- static int fixedPoint[] = { 8, 8, 6, 8, -1, 6, 2, 2, 0 };
- float vtx[9][2], fvtx[9][2];
- float x0, x1, x2, y0, y1, y2, t1, t2, l;
- int index, i;
-
- pw->paint.region.offX = event->x;
- pw->paint.region.offY = event->y;
- pw->paint.region.baseX = event->x_root - w->core.x;
- pw->paint.region.baseY = event->y_root - w->core.y;
-
- pw->paint.region.isTracking = True;
-
- /*
- ** Compute which grip was grabbed, to determine constrain line.
- */
- for (index = 0; index < 9 && pw->paint.region.grip[index] != w; index++)
- ;
-
- createVtxPts(pw, vtx, False, False);
- createVtxPts(pw, fvtx, True, False);
-
- x0 = vtx[0][0]; y0 = vtx[0][1];
- x1 = vtx[2][0]; y1 = vtx[2][1];
- x2 = vtx[6][0]; y2 = vtx[6][1];
-
- pw->paint.region.lineBase[0] = 0;
- pw->paint.region.lineBase[1] = 0;
-
- t1 = x1 - x0; t2 = y1 - y0;
- l = sqrt(t1 * t1 + t2 * t2);
- pw->paint.region.lineDelta[0] = t1 / l;
- pw->paint.region.lineDelta[1] = t2 / l;
-
- t1 = x2 - x0; t2 = y2 - y0;
- l = sqrt(t1 * t1 + t2 * t2);
- pw->paint.region.lineDelta[2] = t1 / l;
- pw->paint.region.lineDelta[3] = t2 / l;
-
- pw->paint.region.startScaleX = pw->paint.region.scaleX;
- pw->paint.region.startScaleY = pw->paint.region.scaleY;
-
- /*
- ** Now compute which corner of the 4 cornerd box doesn't move
- ** as the object is resized.
- */
- for (i = 0; i < 4; i++) {
- float fx = vtx[fixedPoint[index]][0];
- float fy = vtx[fixedPoint[index]][1];
- float px = fvtx[i][0] - pw->paint.region.centerX;
- float py = fvtx[i][1] - pw->paint.region.centerY;
-
- if (ZERO(fx - px) && ZERO(fy - py))
- break;
- }
- pw->paint.region.fixedPoint = i;
- }
- static void regionButtonPress(Widget w, PaintWidget pw, XButtonEvent *event, Boolean *junk)
- {
- pw->paint.region.isRotate = event->button == Button2;
-
- pw->paint.region.offX = event->x;
- pw->paint.region.offY = event->y;
- pw->paint.region.baseX = event->x_root - w->core.x;
- pw->paint.region.baseY = event->y_root - w->core.y;
-
- if (pw->paint.region.isRotate) {
- int dx, dy;
-
- XDefineCursor(XtDisplay(w), XtWindow(pw->paint.region.child), XCreateFontCursor(XtDisplay(w), XC_exchange));
-
- dx = event->x - pw->paint.region.rect.width / 2;
- dy = event->y - pw->paint.region.rect.height / 2;
- pw->paint.region.lastAngle = atan2((double)dy, (double)dx);
- }
-
- /*
- ** Only draw the interactive box when we are rotating.
- */
- pw->paint.region.isTracking = pw->paint.region.isRotate;
- }
- static void gripRelease(Widget w, PaintWidget pw, XButtonEvent *event, Boolean *junk)
- {
- pw->paint.region.isTracking = False;
- drawRegionBox(pw, False);
- #ifndef INTERACTIVE
- if (pw->paint.region.needResize) {
- regionResizeWindow(pw, False);
- regionRedraw(pw);
- }
- #endif
- }
- static void regionButtonRelease(Widget w, PaintWidget pw, XButtonEvent *event, Boolean *junk)
- {
- pw->paint.region.isTracking = False;
- drawRegionBox(pw, False);
-
- if (!pw->paint.region.isRotate)
- return;
-
- #ifndef INTERACTIVE
- if (pw->paint.region.needResize) {
- regionResizeWindow(pw, False);
- regionRedraw(pw);
- }
- #endif
-
- XDefineCursor(XtDisplay(w), XtWindow(pw->paint.region.child), XCreateFontCursor(XtDisplay(w), XC_fleur));
- }
- static void regionGrab(Widget w, PaintWidget pw, XMotionEvent *event, Boolean *junk)
- {
- int dx, dy, nx, ny;
-
- while (XCheckTypedWindowEvent(XtDisplay(w), XtWindow(w), MotionNotify, (XEvent*)event));
-
- PwRegionTear((Widget)pw);
-
- if (pw->paint.region.isRotate) {
- double da, na;
- pwMatrix m;
-
- dx = event->x - pw->paint.region.rect.width / 2;
- dy = event->y - pw->paint.region.rect.height / 2;
- na = atan2((double)dy, (double)dx);
- da = na - pw->paint.region.lastAngle;
- pw->paint.region.lastAngle = na;
-
- m[0][0] = cos(da);
- m[0][1] = -sin(da);
- m[1][0] = sin(da);
- m[1][1] = cos(da);
-
- PwRegionAppendMatrix((Widget)pw, m);
- } else {
- int zoom = GET_ZOOM(pw);
-
- nx = event->x_root - pw->paint.region.baseX;
- ny = event->y_root - pw->paint.region.baseY;
-
- dx = (nx - w->core.x) / zoom;
- dy = (ny - w->core.y) / zoom;
-
- if (dx == 0 && dy == 0)
- return;
-
- pw->paint.region.rect.x += dx;
- pw->paint.region.rect.y += dy;
-
- nx = (pw->paint.region.rect.x - pw->paint.zoomX) * zoom;
- ny = (pw->paint.region.rect.y - pw->paint.zoomY) * zoom;
-
- XtMoveWidget(pw->paint.region.child, nx - BW, ny - BW);
- }
- }
- static void regionExpose(Widget w, PaintWidget pw, XEvent *event, Boolean *junk)
- {
- XImage *xim = NULL;
- XRectangle rect, nrect;
- int isExpose;
- int zoom = GET_ZOOM(pw);
-
- if (!pw->paint.region.isVisible)
- return;
-
- if (event == NULL) {
- isExpose = True;
- rect.x = 0;
- rect.y = 0;
- rect.width = w->core.width;
- rect.height = w->core.height;
- } else if (event->xany.type == Expose) {
- rect.x = event->xexpose.x;
- rect.y = event->xexpose.y;
- rect.width = event->xexpose.width;
- rect.height = event->xexpose.height;
- isExpose = True;
- } else if (event->xany.type == ConfigureNotify) {
- isExpose = False;
- rect.x = 0;
- rect.y = 0;
- rect.width = w->core.width;
- rect.height = w->core.height;
- } else {
- return;
- }
-
- #ifndef INTERACTIVE
- if (pw->paint.region.isTracking) {
- drawRegionBox(pw, True);
- return;
- }
- #endif
- if (pw->paint.region.needResize)
- doResize(pw);
-
- if (zoom != 1) {
- int width, height;
- int pixW, pixH;
-
- nrect.x = rect.x / zoom;
- nrect.y = rect.y / zoom;
- width = (rect.width + zoom - 1) / zoom;
- height = (rect.height + zoom - 1) / zoom;
- /*
- ** It is possible for this top happen, when resizes and
- ** redraws are slightly out of sync.
- */
- pixW = pw->paint.region.rect.width / zoom;
- pixH = pw->paint.region.rect.height / zoom;
- if (width + nrect.x > pixW)
- width = pixW - nrect.x;
- if (height + nrect.y > pixH)
- height = pixH - nrect.y;
- if (width <= 0 || height <= 0)
- return;
- nrect.width = width;
- nrect.height = height;
- }
-
- if (isExpose) {
- if (zoom == 1) {
- XCopyArea(XtDisplay(w), pw->paint.region.source, XtWindow(w),
- pw->paint.region.fg_gc == None ? pw->paint.tgc : pw->paint.region.fg_gc,
- rect.x, rect.y, rect.width, rect.height, rect.x, rect.y);
- } else {
- XImage *src, *msk = NULL;
- XRectangle tr;
-
- tr = nrect;
- tr.x = 0;
- tr.y = 0;
-
- src = XGetImage(XtDisplay(pw), pw->paint.region.source,
- nrect.x, nrect.y, nrect.width, nrect.height,
- AllPlanes, ZPixmap);
- if (pw->paint.region.mask != None)
- msk = XGetImage(XtDisplay(pw), pw->paint.region.mask,
- nrect.x, nrect.y, nrect.width, nrect.height,
- AllPlanes, ZPixmap);
- _PwZoomDraw(pw, w, pw->paint.tgc, src, msk,
- False, nrect.x, nrect.y, zoom, &tr);
- XDestroyImage(src);
- if (msk != NULL)
- XDestroyImage(msk);
- }
- }
-
- /*
- ** XXX -- This should merge, and do fun things.. but.
- */
- if (isExpose && (event != NULL && event->xexpose.count != 0))
- return;
-
- if (pw->paint.region.mask != None) {
- int x = w->core.x + w->core.border_width;
- int y = w->core.y + w->core.border_width;
-
- /*
- ** Copy in the background picture
- */
- if (GET_ZOOM(pw) != 1) {
- XRectangle tr;
- XImage *nmsk;
- int dx = 0, dy = 0;
- PaintWidget tpw = (pw->paint.paint == None) ? pw : (PaintWidget)pw->paint.paint;
- int width, height;
-
- tr.x = (nrect.x + x) / zoom + pw->paint.zoomX;
- tr.y = (nrect.y + y) / zoom + pw->paint.zoomY;
- width = nrect.width;
- height = nrect.height;
-
- /*
- ** We could use PwGetImage, but it returns
- ** the original image, not the sub-region
- */
- if (tr.x < 0) {
- width += tr.x;
- dx = -tr.x;
- tr.x = 0;
- }
- if (tr.y < 0) {
- height += tr.y;
- dy = -tr.y;
- tr.y = 0;
- }
- if (tr.x + width > tpw->paint.drawWidth)
- width = tpw->paint.drawWidth - tr.x;
- if (tr.y + height > tpw->paint.drawHeight)
- height = tpw->paint.drawHeight - tr.y;
- if (width > 0 && height > 0) {
- tr.width = width;
- tr.height = height;
- xim = XGetImage(XtDisplay(w), GET_PIXMAP(pw),
- tr.x, tr.y, tr.width, tr.height,
- AllPlanes, ZPixmap);
- tr.x = tr.y = 0;
- nmsk = XGetImage(XtDisplay(pw), pw->paint.region.notMask,
- nrect.x + dx, nrect.y + dy, tr.width, tr.height,
- AllPlanes, ZPixmap);
-
- _PwZoomDraw(pw, w, pw->paint.tgc, xim, nmsk, False,
- dx, dy, zoom, &tr);
- XDestroyImage(nmsk);
- XDestroyImage(xim);
- }
- } else {
- XCopyArea(XtDisplay(w), GET_PIXMAP(pw), XtWindow(w),
- pw->paint.region.bg_gc,
- x, y, w->core.width, w->core.height, 0, 0);
- }
- }
- }
- static void regionMove(Widget w, PaintWidget pw, XEvent *event, Boolean *junk)
- {
- if (pw->paint.region.mask == None)
- return;
- /*
- ** For some reason, I had to generate an extra function..
- */
- regionExpose(w, pw, event, junk);
- }
-
-
- static void regionSetGripCursors(PaintWidget pw)
- {
- static int cursors[9][2] = {
- { XC_top_left_corner, NorthWestGravity },
- { XC_top_side, NorthGravity },
- { XC_top_right_corner, NorthEastGravity },
- { XC_left_side, WestGravity },
- { 0, 0 },
- { XC_right_side, EastGravity },
- { XC_bottom_left_corner, SouthWestGravity },
- { XC_bottom_side, SouthGravity },
- { XC_bottom_right_corner, SouthEastGravity },
- };
- static int list[9] = { None, None, None, None, None, None, None, None, None };
- int i;
-
- if (list[0] == None) {
- for (i = 0; i < 9; i++) {
- if (i != 4)
- list[i] = XCreateFontCursor(XtDisplay(pw), cursors[i][0]);
- }
- }
-
- for (i = 0; i < 9; i++)
- if (i != 4)
- XDefineCursor(XtDisplay(pw), XtWindow(pw->paint.region.grip[i]), list[i]);
- }
-
- static void gripGrab(Widget w, PaintWidget pw, XMotionEvent *event, Boolean *junk)
- {
- static Boolean isLeftEdge[] = {True, False, False,
- True, False, False,
- True, False, False };
- static Boolean isTopEdge[] = { True, True, True,
- False, False, False,
- False, False, False };
- static Boolean isMiddle[] = { False, True, False,
- True, False, True,
- False, True, False };
- Boolean sameScale;
- int index, i, fp;
- int zoom = GET_ZOOM(pw);
- float v[2];
- int width, height;
- float ovtx[9][2], nvtx[9][2];
- float dx, dy;
-
- for (index = 0; index < 9 && pw->paint.region.grip[index] != w; index++)
- ;
-
- /*
- ** Find the intersection point
- */
- for (i = 0; i < 2; i++) {
- float x0 = pw->paint.region.lineBase[0];
- float y0 = pw->paint.region.lineBase[1];
- float xm = event->x;
- float ym = event->y;
-
- dx = pw->paint.region.lineDelta[0 + i * 2];
- dy = pw->paint.region.lineDelta[1 + i * 2];
- v[i] = dx * (xm - x0) - dy * (y0 - ym);
- }
-
- if (pw->paint.region.startScaleX < 0)
- v[0] = -v[0];
- if (pw->paint.region.startScaleY < 0)
- v[1] = -v[1];
- if (isLeftEdge[index])
- v[0] = -v[0];
- if (isTopEdge[index])
- v[1] = -v[1];
-
- v[0] /= (float)zoom;
- v[1] /= (float)zoom;
-
- PwRegionTear((Widget)pw);
-
- sameScale = False;
- if (isMiddle[index] || (event->state & ShiftMask) != 0) {
- /*
- ** Apply the constraint
- */
- if (index == 1 || index == 7)
- v[0] = 0;
- else if (index == 3 || index == 5)
- v[1] = 0;
- else
- sameScale = True;
- }
-
- width = pw->paint.region.startScaleX * pw->paint.region.orig.width;
- height = pw->paint.region.startScaleY * pw->paint.region.orig.height;
-
- createVtxPts(pw, ovtx, True, False);
-
- pw->paint.region.scaleX = (float)((int)( width + v[0]))/pw->paint.region.orig.width;
- pw->paint.region.scaleY = (float)((int)(height + v[1]))/pw->paint.region.orig.height;
-
- if (sameScale) {
- float sx = ABS(pw->paint.region.scaleX);
- float sy = ABS(pw->paint.region.scaleY);
-
- sx = MIN(sx, sy);
-
- pw->paint.region.scaleX = SIGN(pw->paint.region.scaleX) * sx;
- pw->paint.region.scaleY = SIGN(pw->paint.region.scaleY) * sx;
- }
-
- MKMAT(pw);
- createVtxPts(pw, nvtx, True, False);
-
- fp = pw->paint.region.fixedPoint;
- dx = ovtx[fp][0] - nvtx[fp][0];
- dy = ovtx[fp][1] - nvtx[fp][1];
-
- pw->paint.region.centerX += dx;
- pw->paint.region.centerY += dy;
-
- pw->paint.region.needResize = True;
- regionRedraw(pw);
- }
-
- /*
- **
- **
- */
- static void writeRegion(PaintWidget pw)
- {
- GC gc;
- Pixmap pix, src;
- XRectangle nr;
- int zoom = GET_ZOOM(pw);
-
- if (!pw->paint.region.isVisible)
- return;
- /*
- ** No need to write it, it's still on the drawable.
- */
- if (pw->paint.region.isAttached)
- return;
-
- nr.x = pw->paint.region.rect.x;
- nr.y = pw->paint.region.rect.y;
- nr.width = pw->paint.region.rect.width / zoom;
- nr.height = pw->paint.region.rect.height / zoom;
-
- /*
- ** If we've already modified the background (aka ripped the
- ** image up. Then don't get a new undo buffer.
- ** The second case of the if is if you've done an undo inbetween.
- */
- if (pw->paint.region.undoPixmap == None ||
- pw->paint.region.undoPixmap != GET_PIXMAP(pw))
- pix = PwUndoStart((Widget)pw, &nr);
- else
- pix = pw->paint.region.undoPixmap;
-
- PwUndoAddRectangle((Widget)pw, &nr);
-
- if (pw->paint.region.fg_gc != None) {
- gc = pw->paint.region.fg_gc;
- XSetClipOrigin(XtDisplay(pw), gc, nr.x, nr.y);
- } else {
- gc = pw->paint.tgc;
- }
-
- if (pw->paint.region.proc != NULL) {
- XImage *sim = pw->paint.region.sourceImg;
- Boolean made = False;
-
- if (sim == NULL) {
- sim = XGetImage(XtDisplay(pw),
- pw->paint.region.source, 0, 0,
- pw->paint.region.orig.width,
- pw->paint.region.orig.height, AllPlanes, ZPixmap);
- made = True;
- }
-
- src = (*pw->paint.region.proc)((Widget)pw, sim, pw->paint.region.mat);
- if (made)
- XDestroyImage(sim);
- } else {
- src = pw->paint.region.source;
- }
-
- XCopyArea(XtDisplay(pw), src, pix, gc,
- 0, 0,
- nr.width, nr.height,
- nr.x, nr.y);
-
- if (pw->paint.region.fg_gc != None)
- XSetClipOrigin(XtDisplay(pw), gc, 0, 0);
-
- PwUpdate((Widget)pw, &nr, False);
- }
-
- /*
- ** Called when the parent widgets zoom factor changes
- */
- static void zoomValueChanged(Widget w, XtPointer junk1, XtPointer junk2)
- {
- PaintWidget pw = (PaintWidget)w;
- int zoom = GET_ZOOM(pw);
- int nx, ny;
- int nw, nh;
-
- if (zoom == pw->paint.region.curZoom)
- return;
-
- if (!pw->paint.region.isVisible)
- return;
-
- nx = (pw->paint.region.rect.x - pw->paint.zoomX) * zoom;
- ny = (pw->paint.region.rect.y - pw->paint.zoomY) * zoom;
- nw = (pw->paint.region.rect.width / pw->paint.region.curZoom) * zoom;
- pw->paint.region.rect.width = nw;
- nh = (pw->paint.region.rect.height / pw->paint.region.curZoom) * zoom;
- pw->paint.region.rect.height = nh;
- pw->paint.region.curZoom = zoom;
-
- XtMoveWidget(pw->paint.region.child, nx - BW, ny - BW);
- XtResizeWidget(pw->paint.region.child, nw, nh, BW);
-
- pw->paint.region.needResize = True;
- moveGrips(pw);
- regionRedraw(pw);
- }
-
- void pwRegionZoomPosChanged(PaintWidget pw)
- {
- int nx, ny;
- int zoom;
-
- if (!pw->paint.region.isVisible)
- return;
-
- zoom = GET_ZOOM(pw);
-
- nx = (pw->paint.region.rect.x - pw->paint.zoomX) * zoom;
- ny = (pw->paint.region.rect.y - pw->paint.zoomY) * zoom;
-
- XtMoveWidget(pw->paint.region.child, nx - BW, ny - BW);
- }
-
-
- static void writeCleanRegion(PaintWidget pw, Boolean flag)
- {
- if (!pw->paint.region.isVisible)
- return;
-
- writeRegion(pw);
-
- /*
- ** Free up temporary images
- */
- if (pw->paint.region.sourceImg != NULL)
- XDestroyImage(pw->paint.region.sourceImg);
- if (pw->paint.region.maskImg != NULL)
- XDestroyImage(pw->paint.region.maskImg);
-
- pw->paint.region.sourceImg = NULL;
- pw->paint.region.maskImg = NULL;
- if (pw->paint.region.source != None) {
- XFreePixmap(XtDisplay(pw), pw->paint.region.source);
- pw->paint.region.source = None;
- }
- if (pw->paint.region.mask != None) {
- XFreePixmap(XtDisplay(pw), pw->paint.region.mask);
- pw->paint.region.mask = None;
- }
- if (pw->paint.region.notMask != None) {
- XFreePixmap(XtDisplay(pw), pw->paint.region.notMask);
- pw->paint.region.notMask = None;
- }
-
- pw->paint.region.undoPixmap = None;
-
- if (flag) {
- if (pw->paint.region.child != None)
- XtUnmapWidget(pw->paint.region.child);
- pw->paint.region.isVisible = False;
- }
- }
-
- void PwRegionFinish(Widget w, Boolean flag)
- {
- PaintWidget pw = (PaintWidget)w;
- PaintWidget pp = (PaintWidget)pw->paint.paint;
- PaintWidget tpw;
- int i;
-
- if (flag) {
- tpw = (pp == None) ? pw : pp;
- writeCleanRegion(tpw, True);
- for (i = 0; i < tpw->paint.paintChildrenSize; i++)
- writeCleanRegion((PaintWidget)tpw->paint.paintChildren[i], True);
- doCallbacks(pw, False);
- } else {
- writeCleanRegion(pw, True);
- }
- }
-
- void PwRegionSet(Widget w, XRectangle *rect, Pixmap pix, Pixmap mask)
- {
- PaintWidget pw = (PaintWidget)w;
- int i;
- int nx, ny, x, y, width, height;
- int zoom = GET_ZOOM(pw);
- Boolean setIsAttached = False;
-
- /*
- ** If there is an image, write it
- ** rect == NULL, then this is just a "write" & "unmap" request
- */
- PwRegionFinish(w, True);
- if (rect == NULL)
- return;
-
- pw->paint.region.curZoom = zoom;
-
- x = (rect->x + pw->paint.zoomX) * zoom;
- y = (rect->y + pw->paint.zoomY) * zoom;
- width = rect->width * zoom;
- height = rect->height * zoom;
-
- /*
- ** A little "initializing"
- */
- pw->paint.region.isDrawn = False;
- pw->paint.region.isTracking = False;
- pw->paint.region.needResize = False;
-
- pw->paint.region.rect = *rect;
-
- if (pix == None) {
- setIsAttached = True;
-
- if (rect->x < 0) {
- rect->width += rect->x;
- rect->x = 0;
- }
- if (rect->y < 0) {
- rect->height += rect->y;
- rect->y = 0;
- }
- if (rect->width > pw->paint.drawWidth)
- rect->width = pw->paint.drawWidth;
- if (rect->height > pw->paint.drawHeight)
- rect->height = pw->paint.drawHeight;
-
- pw->paint.region.source = XCreatePixmap(XtDisplay(pw), XtWindow(pw),
- rect->width, rect->height,
- pw->core.depth);
- XCopyArea(XtDisplay(pw), GET_PIXMAP(pw), pw->paint.region.source,
- pw->paint.gc,
- rect->x, rect->y,
- rect->width, rect->height,
- 0, 0);
- } else {
- pw->paint.region.source = pix;
- }
-
- pw->paint.region.mask = mask;
- pw->paint.region.orig = *rect;
-
- /*
- ** If there is a clipping mask, create a fg and bg GC with clip-masks
- ** to draw through.
- */
- if (mask != None) {
-
- if (pw->paint.region.fg_gc == None) {
- pw->paint.region.fg_gc = XCreateGC(XtDisplay(w), XtWindow(w), 0, 0);
- pw->paint.region.bg_gc = XCreateGC(XtDisplay(w), XtWindow(w), 0, 0);
- }
-
- /*
- ** Make sure the Mask GC is built.
- */
- GET_MGC(pw, mask);
- regionCreateNotMask(pw);
- } else {
- /*
- ** No clip mask, make sure we aren't using one.
- */
- if (pw->paint.region.fg_gc != None) {
- XSetClipMask(XtDisplay(w), pw->paint.region.fg_gc, None);
- XSetClipMask(XtDisplay(w), pw->paint.region.bg_gc, None);
- }
- }
-
- if (pw->paint.region.child == None) {
- pw->paint.region.child = XtVaCreateWidget("region",
- compositeWidgetClass, w,
- XtNborderWidth, BW,
- NULL);
- XtAddEventHandler(pw->paint.region.child, ButtonPressMask,
- False,
- (XtEventHandler)regionButtonPress,
- (XtPointer)pw);
- XtAddEventHandler(pw->paint.region.child, ButtonReleaseMask,
- False,
- (XtEventHandler)regionButtonRelease,
- (XtPointer)pw);
- XtAddEventHandler(pw->paint.region.child, ButtonMotionMask,
- False,
- (XtEventHandler)regionGrab,
- (XtPointer)pw);
- XtAddEventHandler(pw->paint.region.child, ExposureMask,
- False,
- (XtEventHandler)regionExpose,
- (XtPointer)pw);
- XtAddEventHandler(pw->paint.region.child, StructureNotifyMask,
- False,
- (XtEventHandler)regionMove,
- (XtPointer)pw);
- XtAddCallback((Widget)pw, XtNsizeChanged, (XtCallbackProc)zoomValueChanged, (XtPointer)NULL);
- XtVaSetValues(pw->paint.region.child, XtNx, x, XtNy, y, XtNwidth, width, XtNheight, height, NULL);
- XtManageChild(pw->paint.region.child);
- XDefineCursor(XtDisplay(w), XtWindow(pw->paint.region.child), XCreateFontCursor(XtDisplay(w), XC_fleur));
-
- for (i = 0; i < 9; i++) {
- if (i == 4)
- continue;
-
- pw->paint.region.grip[i] = XtVaCreateManagedWidget("grip",
- gripWidgetClass, pw->paint.region.child,
- XtNwidth, 6,
- XtNheight, 6,
- NULL);
-
- XtAddEventHandler(pw->paint.region.grip[i], ButtonPressMask,
- False,
- (XtEventHandler)gripPress,
- (XtPointer)pw);
- XtAddEventHandler(pw->paint.region.grip[i], ButtonMotionMask,
- False,
- (XtEventHandler)gripGrab,
- (XtPointer)pw);
- XtAddEventHandler(pw->paint.region.grip[i], ButtonReleaseMask,
- False,
- (XtEventHandler)gripRelease,
- (XtPointer)pw);
- }
- regionSetGripCursors(pw);
- pw->paint.region.isVisible = True;
- } else {
- XClearArea(XtDisplay(pw), XtWindow(pw->paint.region.child),
- 0, 0, 0, 0, True);
- }
-
- if (setIsAttached) {
- nx = rect->x;
- ny = rect->y;
- } else {
- nx = pw->paint.downX;
- ny = pw->paint.downY;
- }
- pw->paint.region.rect.x = nx;
- pw->paint.region.rect.y = ny;
- nx -= pw->paint.zoomX;
- ny -= pw->paint.zoomY;
- XtVaSetValues(pw->paint.region.child, XtNx, nx * zoom - BW,
- XtNy, ny * zoom - BW,
- XtNwidth, width,
- XtNheight, height,
- NULL);
-
- pw->paint.region.scaleX = 1.0;
- pw->paint.region.scaleY = 1.0;
- pw->paint.region.centerX = pw->paint.region.orig.width / 2;
- pw->paint.region.centerY = pw->paint.region.orig.height / 2;
- COPY_MAT(matIdentity, pw->paint.region.rotMat);
- MKMAT(pw);
-
- if (zoom != 1) {
- pw->paint.region.rect.width *= zoom;
- pw->paint.region.rect.height *= zoom;
- }
-
- moveGrips(pw);
-
- if (!pw->paint.region.isVisible) {
- XtMapWidget(pw->paint.region.child);
- pw->paint.region.isVisible = True;
- }
-
- #ifdef SHAPE
- XShapeCombineMask(XtDisplay(pw), XtWindow(pw->paint.region.child),
- ShapeBounding, 0, 0, None, ShapeSet);
- #endif
-
- pw->paint.region.isAttached = setIsAttached;
- doCallbacks(pw, True);
- }
-
- static PaintWidget getActiveRegion(PaintWidget pw)
- {
- PaintWidget pp = (PaintWidget)pw->paint.paint;
- PaintWidget tpw = (pp == None) ? pw : pp;
- int i;
-
- if (pw->paint.region.isVisible && pw->paint.region.source != None)
- return pw;
-
- if (tpw->paint.region.isVisible && tpw->paint.region.source != None)
- return tpw;
-
- for (i = 0; i < tpw->paint.paintChildrenSize; i++) {
- PaintWidget p = (PaintWidget)tpw->paint.paintChildren[i];
- if (p->paint.region.source != None)
- return p;
- }
-
- return None;
- }
-
- void PwRegionSetRawPixmap(Widget w, Pixmap pix)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
-
- if (pw == None)
- return;
-
- XFreePixmap(XtDisplay(pw), pw->paint.region.source);
-
- if (pw->paint.region.sourceImg != NULL) {
- XDestroyImage(pw->paint.region.sourceImg);
- pw->paint.region.sourceImg = NULL;
- }
-
- pw->paint.region.source = pix;
-
- doResize(pw);
- regionRedraw(pw);
- }
-
- Boolean PwRegionGet(Widget w, Pixmap *pix, Pixmap *mask)
- {
- Display *dpy = XtDisplay(w);
- Window win = XtWindow(w);
- PaintWidget pw = getActiveRegion((PaintWidget)w);
- Pixmap myMask = None, notMask = None;
- int zoom;
- int width, height;
-
- if (pw == None)
- return False;
- zoom = GET_ZOOM(pw);
- width = pw->paint.region.orig.width;
- height = pw->paint.region.orig.height;
-
- if (pix) *pix = None;
- if (mask) *mask = None;
-
- if (pw->paint.region.source != None && pix != NULL) {
- *pix = XCreatePixmap(dpy, win, width, height, pw->core.depth);
- if (pw->paint.region.sourceImg != NULL) {
- XPutImage(dpy, *pix, pw->paint.tgc,
- pw->paint.region.sourceImg,
- 0, 0, 0, 0, width, height);
- } else {
- XCopyArea(dpy, pw->paint.region.source,
- *pix, pw->paint.tgc,
- 0, 0, width, height, 0, 0);
- }
- }
- if (pw->paint.region.mask != None) {
- myMask = XCreatePixmap(dpy, win, width, height, 1);
- notMask = XCreatePixmap(dpy, win, width, height, 1);
-
- if (pw->paint.region.maskImg != NULL) {
- XPutImage(dpy, myMask, pw->paint.mgc,
- pw->paint.region.maskImg,
- 0, 0, 0, 0, width, height);
- } else {
- XCopyArea(dpy, pw->paint.region.mask,
- myMask, pw->paint.mgc,
- 0, 0, width, height, 0, 0);
- }
-
- XSetFunction(dpy, pw->paint.mgc, GXcopyInverted);
- XCopyArea(dpy, myMask, notMask, pw->paint.mgc, 0, 0,
- width, height, 0, 0);
- XSetFunction(dpy, pw->paint.mgc, GXcopy);
-
- if (mask == NULL)
- XFreePixmap(dpy, myMask);
- else
- *mask = myMask;
- }
- if (notMask != None && pix != NULL) {
- XSetClipOrigin(dpy, pw->paint.igc, 0, 0);
- XSetClipMask(XtDisplay(pw), pw->paint.igc, notMask);
- XFillRectangle(XtDisplay(pw), *pix, pw->paint.igc, 0, 0,
- width, height);
- XSetClipMask(XtDisplay(pw), pw->paint.igc, None);
-
- }
-
- if (notMask != None)
- XFreePixmap(dpy, notMask);
-
- return True;
- }
-
- void PwRegionClear(Widget w)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
-
- if (pw == None)
- return;
-
- PwRegionTear(w);
-
- pw->paint.region.isVisible = False;
- if (pw->paint.region.child != None)
- XtUnmapWidget(pw->paint.region.child);
- doCallbacks(pw, False);
- }
-
- /*
- ** Insure that the current region is not connected to the
- ** source pixmap.
- */
- void PwRegionTear(Widget w)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
- XRectangle nr;
-
- if (pw == None)
- return;
- if (!pw->paint.region.isAttached || !pw->paint.region.isVisible)
- return;
-
- nr = pw->paint.region.rect;
- nr.width /= GET_ZOOM(pw);
- nr.height /= GET_ZOOM(pw);
-
- pw->paint.region.undoPixmap = PwUndoStart((Widget)pw, &nr);
-
- if (pw->paint.region.mask != None) {
- XSetClipOrigin(XtDisplay(pw), pw->paint.igc, nr.x, nr.y);
- XSetClipMask(XtDisplay(pw), pw->paint.igc, pw->paint.region.mask);
- }
- #if 0
- if (pw->paint.sourcePixmap == None) {
- #endif
- XFillRectangles(XtDisplay(pw), pw->paint.region.undoPixmap,
- pw->paint.igc, &nr, 1);
- #if 0
- } else {
- XCopyArea(XtDisplay(pw), pw->paint.sourcePixmap, pw->paint.region.undoPixmap,
- pw->paint.igc,
- nr.x, nr.y,
- nr.width, nr.height,
- nr.x, nr.y);
- }
- #endif
- PwUpdate((Widget)pw, &nr, False);
- if (pw->paint.region.mask != None) {
- XSetClipOrigin(XtDisplay(pw), pw->paint.igc, 0, 0);
- XSetClipMask(XtDisplay(pw), pw->paint.igc, None);
- }
- pw->paint.region.isAttached = False;
- }
-
- void PwRegionAppendMatrix(Widget w, pwMatrix mat)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
-
- if (pw == None)
- return;
-
- PwRegionTear((Widget)pw);
-
- mm(pw->paint.region.rotMat, mat, pw->paint.region.rotMat);
- MKMAT(pw);
-
- pw->paint.region.needResize = True;
- regionResizeWindow(pw, False);
- regionRedraw(pw);
- }
-
- void PwRegionSetMatrix(Widget w, pwMatrix mat)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
-
- if (pw == None)
- return;
-
- PwRegionTear((Widget)pw);
-
- COPY_MAT(mat, pw->paint.region.rotMat);
- MKMAT(pw);
-
- pw->paint.region.needResize = True;
- regionResizeWindow(pw, False);
- regionRedraw(pw);
- }
-
- void PwRegionAddScale(Widget w, float *xs, float *ys)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
-
- if (pw == None)
- return;
-
- if (xs != NULL)
- pw->paint.region.scaleX *= *xs;
- if (ys != NULL)
- pw->paint.region.scaleY *= *ys;
-
- MKMAT(pw);
-
- pw->paint.region.needResize = True;
- regionResizeWindow(pw, False);
- regionRedraw(pw);
- }
-
- void PwRegionSetScale(Widget w, float *xs, float *ys)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
-
- if (pw == None)
- return;
-
- if (xs != NULL)
- pw->paint.region.scaleX = *xs;
- if (ys != NULL)
- pw->paint.region.scaleY = *ys;
-
- MKMAT(pw);
-
- pw->paint.region.needResize = True;
- regionResizeWindow(pw, False);
- regionRedraw(pw);
- }
-
- void PwRegionReset(Widget w, Boolean flag)
- {
- PaintWidget pw = getActiveRegion((PaintWidget)w);
- pwMatrix mat;
-
- if (pw == None)
- return;
-
- PwRegionTear((Widget)pw);
-
- mat[0][0] = mat[1][1] = 1;
- mat[1][0] = mat[0][1] = 0;
-
- COPY_MAT(mat, pw->paint.region.rotMat);
- pw->paint.region.scaleY = 1.0;
- pw->paint.region.scaleX = 1.0;
- MKMAT(pw);
-
- pw->paint.region.needResize = True;
- regionResizeWindow(pw, False);
- regionRedraw(pw);
-
- /* XXX flag should reset X & Y position as well */
- }
-